/*
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jserver.gameserver.custom;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.l2jserver.L2DatabaseFactory;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.instance.L2HonorPointsManagerInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.skills.Stats;
import com.l2jserver.gameserver.templates.StatsSet;

/**
 * @author Home
 *
 */
public class HonorPointsManager
{
	private static final Logger _log = Logger.getLogger(HonorPointsManager.class.getName());
	private final ArrayList<Stats> _allowedStats = new ArrayList<Stats>(6);
	private final HashMap<Integer, HonorRankModel> _ranks = new HashMap<Integer, HonorRankModel>(3);
	private final HashMap<Integer, PcHonor> _playersData = new HashMap<Integer, PcHonor>(10);
	private final HashMap<String, String> _honorReward = new HashMap<String, String>(6);
	
	private HonorPointsManager()
	{
		load();
	}
	
	@Deprecated
	public boolean hasHonors(L2PcInstance player)
	{
		return _playersData.containsKey(player.getObjectId());
	}
	
	public int getHonorAmount(String killType)
	{
		String value = _honorReward.get(killType);
		return value != null ? new Integer(value) : 0;
	}
	
	public void setHonorToPc(L2PcInstance player)
	{
		PcHonor honor = _playersData.get(player.getObjectId());
		if (honor != null && honor.hasOwner())
		{
			honor.updateStatCalcs();
			honor.updateTitleColor();
			return;
		}
		
		if (honor != null)
		{
			honor.setOwner(player);
		}
		else
		{
			honor = new PcHonor(player.getObjectId(), HonorRankModel.RANK_0);
			honor.setOwner(player);
			_playersData.put(player.getObjectId(), honor);
			ThreadPoolManager.getInstance().scheduleGeneral(new L2HonorPointsManagerInstance.InsertHonor(honor), (long) 1E3);
		}
	}
	
	public boolean isAllowed(Stats stat)
	{
		return _allowedStats.contains(stat);
	}
	
	public final List<Stats> getAlowedStats()
	{
		return Collections.unmodifiableList(_allowedStats);
	}
	
	public final Map<Integer, HonorRankModel> getRanks()
	{
		return Collections.unmodifiableMap(_ranks);
	}
	
	public PcHonor getHonor(int objectId)
	{
		return _playersData.get(objectId);
	}
	
	public void setHonor(int objId, PcHonor honor)
	{
		if (honor.getOwnerId() != objId)
		{
			_log.warning("Tried to link an honor to a diffetent ownerId. Old ID " + honor.getOwnerId() + " New ID " + objId);
			return;
		}
		_playersData.put(objId, honor);
	}
	
	/**
	 * 
	 */
	private void load()
	{
		Connection con = null;
		try
		{
			
			//load xml
			File file = new File("./config/ranks.xml");
			if (!file.exists())
			{
				_log.severe(file.getPath() + " doesn't exist.");
				return;
			}
			Document doc = null;
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(false);
			factory.setIgnoringComments(true);
			doc = factory.newDocumentBuilder().parse(file);
			for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
			{
				if ("config".equalsIgnoreCase(n.getNodeName()))
				{
					for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
					{
						if ("allowedStats".equalsIgnoreCase(d.getNodeName()))
						{
							String stats = d.getAttributes().getNamedItem("value").getNodeValue();
							if (stats.contains(";"))
							{
								for (String stat : stats.split(";"))
								{
									_allowedStats.add(Stats.valueOfXml(stat));
								}
							}
							else
							{
								_allowedStats.add(Stats.valueOfXml(stats));
							}
						}
						else if ("honorReward".equalsIgnoreCase(d.getNodeName()))
						{
							String vlues = d.getAttributes().getNamedItem("value").getNodeValue();
							String[] opts = vlues.split(";");
							for (String s : opts)
							{
								String key = s.split(",")[0];
								String value = s.split(",")[1];
								_honorReward.put(key, value);
							}
						}
						else if ("rank".equalsIgnoreCase(d.getNodeName()))
						{
							StatsSet set = new StatsSet();
							NamedNodeMap attribs = d.getAttributes();
							set.set("rank_level", attribs.getNamedItem("level").getNodeValue());
							set.set("stat_points", attribs.getNamedItem("points").getNodeValue());
							set.set("title_color1", attribs.getNamedItem("titleColor1").getNodeValue());
							set.set("title_color2", attribs.getNamedItem("titleColor2").getNodeValue());
							set.set("rank_price", attribs.getNamedItem("price").getNodeValue());
							set.set("rank_item", attribs.getNamedItem("item").getNodeValue());
							set.set("item_amount", attribs.getNamedItem("amount").getNodeValue());
							set.set("rank_name", attribs.getNamedItem("name").getNodeValue());
							HonorRankModel model = new HonorRankModel(set);
							_ranks.put(model.getRankLevel(), model);
						}
					}
				}
			}
			//end load xml
			
			//load table
			//load player rank/points
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement = con.prepareStatement("SELECT * FROM player_honors");
			ResultSet result = statement.executeQuery();
			
			while (result.next())
			{
				int objId = result.getInt("objectId");
				int rankLvl = result.getInt("rankLevel");
				int statPointsLeft = result.getInt("stats_left");
				int honorPointsLeft = result.getInt("honors_left");
				HonorRankModel pRank = null;
				if (rankLvl > 0)
					pRank = _ranks.get(rankLvl);
				else
					pRank = HonorRankModel.RANK_0;
				PcHonor pchonor = new PcHonor(objId, pRank);
				pchonor.setHonorPoints(honorPointsLeft);
				pchonor.setStatPoints(statPointsLeft);
				_playersData.put(pchonor.getOwnerId(), pchonor);
				
			}
			
			//load players stat bonus
			PreparedStatement st = con.prepareStatement("SELECT * FROM honor_stats");
			ResultSet res = st.executeQuery();
			
			while (res.next())
			{
				int playerId = res.getInt("objectId");
				String statName = res.getString("statName");
				Stats stat = Stats.valueOfXml(statName);
				int bonus = res.getInt("bonus");
				PcHonor pcHonor = _playersData.get(playerId);
				if (pcHonor != null)
				{
					pcHonor.addStat(stat, bonus);
				}
			}
			//end load table
		}
		catch (Exception e)
		{
			_log.log(Level.SEVERE, null, e);
		}
		finally
		{
			try
			{
				con.close();
			}
			catch (Exception e)
			{
			}
		}
		
	}
	
	public static HonorPointsManager getInstance()
	{
		return SingletonHolder._instance;
	}
	
	private static class SingletonHolder
	{
		protected static final HonorPointsManager _instance = new HonorPointsManager();
	}
	
}
